home *** CD-ROM | disk | FTP | other *** search
- /*
- cop.hfm -- C Object Programming: object
- header template.
-
- (C) Copyright 1992 John W. Small
- All rights reserved
-
- PSW / Power SoftWare
- P.O. Box 10072
- McLean, Virginia 22102 8072 USA
- Voice: (703) 759-3838
-
-
- Always edit a cloned copy of this file. With
- the case-sensitive flag set and word-only
- flag reset ...
-
- Find and Replace with something like
-
- structFileName foobar
- structType foobar
- structFncPrefix FB
-
- Edit the remaining text to fully declare your
- new object. This file is setup to suggest
- that your new object inherits three previously
- declared objects (base1, base2, and base3),
- the first of which has inherited two more
- objects. The third is a virtual base class.
- All the objects in the hierarchy supposedly
- have vFt's (Virtual Function Tables) that have
- one or more vF's overridden by the object being
- declared. Simply delete those items not
- pertaining to the new object you're declaring.
- You should find enough structure here to guide
- you in expanding this boiler plate for more
- complicated hierarchies if need be.
-
- Find and replace with something like
-
- base1FileName strawber
- base1StructType Strawberry
- base1StructFncPrefix SWB
-
- or delete those lines containing unnecessary
- items. Complete the find and replace process
- for base11, base12, base2, and base3 and delete
- any comments you find inappropriate such as
- this one.
- */
-
-
-
- /*
- To simulate C++ templates include the following
- #ifdef statement at this point in your struct's
- header file.
-
- #ifdef CLASS_T
- #undef structFileName_H
- #endif
-
- Code the header and source files as usual for
- your struct. Where the C++ approach would be
-
- template <class CLASS_T>
- struct structType ...
- ... CLASS_T ...
-
- The COP approach would be:
-
- struct_(structType_CLASS_T)
- { ... CLASS_T ... };
- ... CLASS_T ...
-
-
- To invoke a template instance of your struct
- instead of the usual C++ approach:
-
- structType<CLASS_T>;
-
- use the following:
-
- #define CLASS_T ???
- #include "structFileName.h"
-
-
- The structFileName.h header file will pull in
- the structFileName.c source file leaving
- CLASS_T undefined so that the process can be
- used again. Another advantage of this approach
- is that both the header and source files can be
- cloned and CLASS_T globally replaced with the
- correct type by any editor to produce the same
- effect; however, the cloned source files can
- then be further edited to go beyond template
- adaptibility.
- */
-
-
- /*
- structFileName.h -- COP object header
- */
-
- #ifndef structFileName_H
- #define structFileName_H
-
- #ifndef COP_H
- #include "cop.h"
- #endif
-
- /*
-
- Pointers to types have the same name as the
- type only the last letter capitalized. For
- example if "vf" stands for virtual function
- then you can infer that "vF" stands for a
- pointer to a virtual function. "vFt" stands
- for a virtual function pointer table so what
- would you think that "vFT" stands for? That's
- right, a pointer to a virtual function pointer
- table! This convention is used thoughout.
- "thiS" is always a pointer to a struct
- instance. "thiS" is always assumed to be a
- valid, non-NULL value unless it is specified as
- "thiS_0" which means thiS or NULL is expected.
- Specifying that "thiS" is never NULL allows
- most member functions to be more efficient.
- "thiS_0" should only and must be used with the
- struct_init_???() and struct_destruct() macros
- and your public constructor/destructor macros.
- A NULL value signals a constructor to
- dynamically allocate memory for the instance
- being constructed.
-
- */
-
-
- /*
- Include only directly inherited struct
- header files since these in turn will include
- any header files necessary for their inherited
- structs!
- */
-
- #ifndef base1FileName_H
- #include "base1FileName.h"
- #endif
-
- #ifndef base2FileName_H
- #include "base2FileName.h"
- #endif
-
- #ifndef base3FileName_H
- #include "base3FileName.h"
- #endif
-
-
-
- /*
- Forward declare structType's vFt struct if new
- vF's are introduced at this level.
- */
-
- struct_vFt_forward(structType);
-
-
-
- /* structType data declarations */
-
- struct_(structType) {
-
- /*
- All struct data members are considered
- private; access only via member functions
- or macros!
- */
-
-
- /* multiple inheritance */
-
- inherit(base1StructType);
- inherit(base2StructType);
- vbInherit(base3StructType);
-
-
- /*
- Add a pointer to the vFt which houses the new
- vfs introduced at the structType level.
- */
-
- vFT_decl(structType);
-
-
- /*
- Polymorphic() is required here if any struct
- in the hierarchy, inclusive, has a vFT! In
- other words any struct introducing a vFT and
- all structs in a hierarchy derived from such a
- struct are required to have a polymorphic()
- member! The polymorphic() macro expands to a
- descendanT pointer. This allows the virtual
- functions to adjust their "thiS" pointers to
- the correct instance struct. Structs with
- "descendanT" pointers are said to belong to
- polymorphic clusters. Structs with vFTs are
- said to be polymorphic cluster root structs.
- Polymorphic clusters can themselves contain
- other polymorphic clusters, i.e. a partial
- ordering.
- */
-
- polymorphic();
-
-
- /* data members added at structType level */
-
- ...
-
-
- };
-
-
-
- /*
- A host structure having a virtual base
- structure must have a casing structure to hold
- the host and virtual base structures. Since
- virtual bases are only included once in a
- heirarchy they can't be contained directly in
- the host structure as with the case with
- regularly inherited structures. If the host is
- inherited by yet another structure then that
- derived structure must have a casing structure
- leaving the intermediate casing structure
- unused.
-
- Only host structures have member functions.
- To use a casing struct thiS pointer with a host
- function you must convert it to the host thiS.
- Use the vbhThiS() macro to convert a casing
- struct thiS pointer to its corresponding
- host struct thiS pointer.
- */
-
- struct_vbc(structType) {
- vbh_decl(structType);
- vb_decl(base3StructType);
- /*
- A casing structure has only one host structure
- and one or more virtual base structures.
- */
- };
-
-
-
-
- /*
- Define typecasts to/from structType.
- Follow this chaining format even if you don't
- have an immediate use for some of the macros.
- By following this format your structs will be
- extensible later. In fact the macros here
- assume that the format was followed by the
- base1Struct and call its macros to reach
- base11 and base12 which are supposedly
- inherited by base1.
-
- Base1 is assumed to be a polymorphic focus that
- processing will center around, hence the
- polyBaseThiS_0_decl() function declaration.
- The corresponding function definition in
- cop.cfm allows the upcasting of "thiS_0"
- pointers to the polymorphic root on the fly
- which is unattainable with nested macros. The
- corresponding polyBaseThiS_0_def() expansion
- in cop.cfm assumes the previous definition of
- structFncPrefix_base1StructTypeThiS() macro.
- It should well known at the current level what
- polymorphic root code future derived instances
- will need to be implicitly upcasted to an thus
- only those casts need to be declared with
- polyBaseThiS_0_decl().
- */
-
- #define structFncPrefix_base1StructTypeThiS(thiS) \
- baseThiS(thiS,base1StructType)
- polyBaseThiS_0_decl(structFncPrefix,
- base1StructType,structType);
- #define structFncPrefix_base11StructTypeThiS(thiS) \
- base1StructFncPrefix_base11StructTypeThiS \
- (baseThiS(thiS,base1StructType))
- #define structFncPrefix_base12StructTypeThiS(thiS) \
- base1StructFncPrefix_base12StructTypeThiS \
- (baseThiS(thiS,base1StructType))
- #define structFncPrefix_base2StructTypeThiS(thiS) \
- baseThiS(thiS,base2StructType)
- #define structFncPrefix_base3StructTypeThiS(thiS) \
- vbThiS(thiS,base3StructType)
- #define base1StructFncPrefix_structTypeThiS(thiS) \
- derivedThiS(thiS,structType)
- #define base11StructFncPrefix_structTypeThiS(thiS) \
- base1StructFncPrefix_structTypeThiS \
- (base11StructFncPrefix_base1StructTypeThiS \
- (thiS))
- #define base12StructFncPrefix_structTypeThiS(thiS) \
- base1StructFncPrefix_structTypeThiS \
- (base12StructFncPrefix_base1StructTypeThiS \
- (thiS))
- #define base2StructFncPrefix_structTypeThiS(thiS) \
- derivedThiS(thiS,structType)
- #define base3StructFncPrefix_structTypeThiS(thiS) \
- vbDerivedThiS(thiS,structType)
-
-
-
- /* Declare structType's static members */
-
- struct_static(structType) {
-
- int StaticVariable;
- ...
-
- };
-
-
-
- /*
- Declare structType's vFt struct for new vF's
- introduced at the structType level.
- */
-
- struct_vFt(structType) {
-
- vF_decl(void,dummyVf,(structType * thiS, ...));
-
-
- /*
- If any base struct in the hierarchy has a
- virtual destructor then override that
- destructor below instead of starting a new
- polymorphic root here! You must always
- override ALL virtual destructors inherited
- regardless of which branch of the hierarchy
- they reside! Thus once a virtual destructor
- is introduced into a hierarchy, descendants'
- destructors can only be virtual overrides!
- Be sure to always use the exact formal
- parameter list shown below.
- */
-
- vF_decl(void, destruct,(structType * thiS,
- unsigned nobj, int malloced));
-
- };
-
-
-
- /* Declare structType's default vFt for new vF's */
-
- vFt_decl(structType,structType);
-
-
- /* Declare vf's for structType's default vFt */
-
- vf_decl(void,structFncPrefix,structFncPrefix,
- dummyVf,(structType * thiS, ...));
- vf_decl(void,structFncPrefix,structFncPrefix,
- destruct,(structType * thiS, unsigned nobj,
- int malloced));
- /*
- In practice you'll find it easy to copy the
- vF_decl()s in struct_vFt() above and
- edit them to read vf_decl(). Of course you'll
- need to add the overriding fnc and spawning
- fnc prefix parameters.
- */
-
-
- /*
- Declare structType's overriding vFt's for all
- BaseStructs within inherited hierarchy having
- vf's overridden at structType level. You must
- always override all virtual destructors
- inherited regardless of which branch of the
- hierarchy they reside! Once a virtual
- destructor is introduced into a hierarchy,
- descendants' destructors can only be virtual
- overrides!
- */
-
- vFt_decl(structType,base1StructType);
-
- vf_decl(base1StructType *,
- structFncPrefix,base1StructFncPrefix,
- vfbase1,(base1StructType * thiS, ...));
- /*
- Repeat the vf_decl() macro for all base1 vfs
- that are overriden at the structType level.
- Note that the overriding vfs retain the thiS
- pointer to the original level struct at which
- they were introduced! In practice you'll find
- it easiest to copy the vf_decl()s from their
- respective base struct headers and edit the
- overriding fnc prefixes to read
- structFncPrefix. Then simply delete those
- lines with vfs that you are not overriding!
- */
-
-
- vFt_decl(structType,base11StructType);
-
- vf_decl(void,structFncPrefix,base11StructFncPrefix,
- vfbase11,(base11StructType * thiS, ...));
-
-
- vFt_decl(structType,base12StructType);
-
- vf_decl(int,structFncPrefix,base12StructFncPrefix,
- vfbase12,(base12StructType * thiS, ...));
-
-
- vFt_decl(structType,base2StructType);
-
- vf_decl(int,structFncPrefix,base2StructFncPrefix,
- vfbase2,(base2StructType * thiS, ...));
-
- vFt_decl(structType,base3StructType);
-
- vf_decl(int,structFncPrefix,base3StructFncPrefix,
- vfbase3,(base3StructType * thiS, ...));
-
-
- /*
- Declare structType's protected constructors
- and destructors. Be sure to follow this
- format even for simple objects to insure that
- they are extensible -- you'll begin to see the
- reasoning once your hierarchies begin to grow
- and especially when you attempt to make
- objects persistent!
- */
-
- struct_initVFTs_decl(structFncPrefix,
- (structType * thiS,
- void * descendanT_0
- , vFT_0_decl(structType)
- /*
- All base structs with vFTs need to be
- initialized thus require their specific formal
- parameter. A null pointer when passed as a
- actual parameter indicates to use the default
- vFT in question (see struct_initVFTs_def).
- */
- , vFT_0_decl(base1StructType)
- , vFT_0_decl(base11StructType)
- , vFT_0_decl(base12StructType)
- , vFT_0_decl(base2StructType)
- /*
- Since a virtual base struct is not contained
- within the host struct you must tell it where
- it does reside with a pointer. The pointer
- points to the virtual base that is in a casing
- struct.
- */
- , vbThiS_decl(base3StructType)
- /*
- If the virtual base is polymorphic then its
- descendant pointer is handled specially. If
- the virtual base is inherited through more then
- one branch the descendant pointer must point
- the most derived struct joining all branches.
- If a casing struct is inherited then that
- becomes the lowest joint as far as the virtual
- base descendant pointer is concerned. If NULL
- is passed then this indicates that a regular
- descendant chain is in effect. Remember the
- virtual function definition must embody the
- knowledge to read these chains as necessary.
- */
- , vbDescendanT_0_decl(base3StructType)
- , vFT_0_decl(base3StructType)
- ));
-
- /*
- Make sure you have enough closing parentheses
- above, typically 3. It is very hard to find
- the bug reported by most C preprocessors if
- you don't!
- */
-
-
- /*
- Define the following two heap management
- macros as shown. If a special heap is to be
- used to instanciate structures, here is the
- place to redefine them. This corresponds to
- C++ class overloading of the new and delete
- operators. To globally overloaded new and
- delete, define MALLOC and FREE macros ahead
- of the inclusion of the cop.h header file or
- edit the MALLOC and FREE macros in cop.h.
- */
-
- #define structFncPrefix_malloc(nobj) \
- MALLOC(sizeof(structType)*nobj)
-
- #define structFncPrefix_free(thiS) FREE(thiS)
-
-
- /*
- This protected constructor is required of all
- cop structures to allow extensibility. The
- protected constructor's thiS_0 parameter
- allows for dynamic allocation. If thiS_0 is
- NULL then the constructor first allocates the
- instance. For a derived structure thiS_0
- may be NULL at the level of instanciation but
- for intermediate level constructor calls
- thiS_0 is never NULL! The nobj parameter
- allows for the construction of vectors of
- instances. For intermediate constructors nobj
- is always 1 (see cop.cfm) since instance is
- completely constructed before moving on to the
- next instance in the vector. Notice here the
- parameter to indicate the location of the
- virtual base3 struct.
- */
-
- struct_init_decl(structType,structFncPrefix,_,
- (structType * thiS_0
- , unsigned nobj
- , vbThiS_decl(base3StructType)
- , ... initializers
- ));
-
- /*
- If you need more than one constructor then
- repeat the struct_inita_decl() macro above
- with an overloaded suffix parameter and the
- appropriate initialization parameters.
- */
-
-
- /*
- This protected destructor is required of all
- cop structures to insure extensibility. See
- comment above struct_init_decl().
- */
-
- struct_destruct_decl(structType,structFncPrefix);
-
-
- /*
- Define structType's public
- constructors and destructors.
- */
-
- #define structFncPrefix_init(thiS_0,nobj, ...) \
- struct_init(structFncPrefix,_, \
- (thiS_0,nobj, ...))
- /* besure to put parentheses around actualParams! */
- #define structFncPrefix_init_default(thiS_0) \
- structFncPrefix_init(thiS_0,1, ...)
- #define structFncPrefix_new(nobj,...) \
- structFncPrefix_init((structType *)0,nobj, \
- ...)
- #define structFncPrefix_new_default() \
- structFncPrefix_new(1,...)
- #define structFncPrefix_destruct(thiS,nobj)
- /*
- Define the structFncPrefix_destruct macro as
- follows:
-
- If a virtual destructor is in use
- if the virtual destructor originates at this level
-
- vf_runTimeBind(thiS,destruct,(thiS,nobj,0))
-
- else
-
- base?StructFncPrefix_destruct \
- (structFncPrefix_base?StructTypeThiS \
- (thiS),nobj)
- //any immediate base with a virtual destructor
-
- else
-
- struct_destruct(structFncPrefix,thiS,nobj,0)
- */
- #define structFncPrefix_delete(thiS_0,nobj)
- /*
- Define the structFncPrefix_delete macro as
- follows:
-
- If a virtual destructor is in use
- if the virtual destructor originates at this level
-
- if (thiS_0) vf_runTimeBind(thiS_0,\
- destruct,(thiS_0,nobj,1)); else
-
- else
-
- if (thiS_0) base?StructFncPrefix_delete \
- (structFncPrefix_base?StructTypeThiS \
- (thiS_0),nobj); else
- //any immediate base with a virtual destructor
-
- else
-
- struct_destruct(structFncPrefix,thiS_0,nobj,1)
- */
-
-
- /*
- Declare structType member functions and
- define structType member macros below.
- Private members should be prefixed with an
- additional "PV_" and protected members with
- "PT_". It is good practice to declare the
- base struct promoted member functions first
- followed by the current level member
- functions. Remember, adherence to strict
- programming style guidelines is the key to
- successfully managing the complexities of OOP
- in a non OOP language!
- */
-
-
- /*
- Base members should be promoted to the current
- structType level as shown below. This way
- only current level functions are used on
- current level instances.
- */
-
- #define structFncPrefix_base1fnc(thiS, ...) \
- base1StructFncPrefix_base1fnc \
- (structFncPrefix_base1StructTypeThiS(thiS), \
- ...)
-
- /*
- To invoke a virtual function at the current
- level use the vf_runTimeBind() macro. All the
- vf declarations above were for the actual
- functions. You'll want to present an
- interface to the user that makes the run time
- binding transparent.
- */
-
- #define structFncPrefix_dummyVf(thiS, ...) \
- vf_runTimeBind(thiS,dummyVf,(thiS, ...));
-
- /*
- To invoke a virtual function originating at a
- base level simply promote the base member
- interface to the current level, e.g.
- */
-
- #define structFncPrefix_vfbase1(thiS, ...) \
- base1StructFncPrefix_vfbase1 \
- (structFncPrefix_base1StructTypeThiS(thiS), \
- ...)
-
-
- /*
- The exact logic for declaring/defining member
- functions is as follows:
-
- If the function is virtual
- if the function originates in a vFt at this level
-
- #define structFncPrefix_fncName(thiS, ...) \
- vf_runTimeBind(thiS,fncName,(thiS, ...))
-
- else
-
- #define structFncPrefix_fncName(thiS, ...) \
- base?StructFncPrefix_fncName \
- (structFncPrefix_base?StructTypeThiS(thiS),\
- ...)
- // Don't define this case if it doesn't make
- // sense to use the structType level for
- // polymorphic processing instead of the
- // polymorphic root itself. Destructors are
- // different since you never know what level
- // you may want to call a virtual destructor
- // from.
-
- else
-
- extern structFncPrefix_fncName
- (structType * thiS, ...);
- */
-
-
- /*
- Use the following convention to translate C++
- overloaded operators
-
- class member operators become:
-
- structFncPrefix_op_???
- (structType * thiS, ...)
-
- and non member operators become:
-
- op_???(...)
-
- where:
-
- operator ???
-
- [] subscript
- () fncCall
- -> select
- ++ inc
- -- dec
- & addr
- * indirect
- + uPlus
- - uMinus
- ~ complement
- ! negate
- sizeof sizeof
- * mult
- / div
- % rmdr
- + plus
- - minus
- << LShift
- >> RShift
- < LT
- > GT
- <= LE
- >= GE
- == EQ
- != NE
- ^ bwXOR
- & bwAND
- | bwOR
- && AND
- || OR
- = asg
- *= asgProd
- /= asgQuot
- %= asgRmdr
- += asgSum
- -= asgDiff
- <<= asgLShift
- >>= asgRShift
- &= asgBwAND
- ^= asgBwXOR
- |= asgBwOR
- , comma
- */
-
-
- /*
- Don't forget static data member access! The
- conditional expression below guarantees that
- we don't have an lvalue so the macro can't be
- wrongly used. Optimization should discard the
- test leaving only the expression we want.
- */
-
- #define structFncPrefix_getStaticVariable() \
- (1? static_ref(structType, \
- StaticVariable) : 1)
-
-
-
-
-
- #endif /* structFileName_H */
-
-
- /*
-
- If you are simulating C++ templates above
- include the following.
-
- #ifdef CLASS_T
- #include "structFileName.c"
- #undef CLASS_T
- #endif
-
- */
-